#include "test01_Namespace.h"


// 命名空间可以嵌套
// 命名空间内可以定义类
// 类中不可以定义命名空间



// 函数的实现

void test01::myNS::test01_Namespace::claMain() 
{
	this->myTest01();

}

void test01::myNS::test01_Namespace::myTest01() 
{
	std::cout << "===test01::myNS::test01_Namespace::myTest01===\n";
}


std::string test01::CodeUtils::GbkToUtf8(const std::string& str)
{
	// ::  = 可能是语法糖或简写
	int nwLen = ::MultiByteToWideChar(CP_ACP, 0, str.c_str(), -1, NULL, 0); // Windows中的函数，将多字节字符串转成宽字节字符串
	// 参数：1-源字符串的代码页，CP_ACP表示使用当前系统的默认代码页
	// 2-转换标志位，一般为0。3-源字符串的指针，以NULL结尾。4-字符串的字节数，如果设置为-1，则函数会自动计算源字符串的长度
	// 5-目标字符串的指针，用于接收转换后的宽字符字符串。6-目标字符串缓冲区的长度，以宽字符数计算

	wchar_t* pwBuf = new wchar_t[nwLen + 1]; // 一定要加1，不然会出现尾巴  
	ZeroMemory(pwBuf, nwLen * 2 + 2); // ZeroMemory-将一块内存区域的所有字节都设置为0，参数为:开始地址，大小

	::MultiByteToWideChar(CP_ACP, 0, str.c_str(), str.length(), pwBuf, nwLen);

	int nLen = ::WideCharToMultiByte(CP_UTF8, 0, pwBuf, -1, NULL, NULL, NULL, NULL);

	char* pBuf = new char[nLen + 1];
	ZeroMemory(pBuf, nLen + 1);

	::WideCharToMultiByte(CP_UTF8, 0, pwBuf, nwLen, pBuf, nLen, NULL, NULL); // 将宽字节字符串转成多字节字符串

	std::string retStr(pBuf);

	delete[] pwBuf; // 手动释放new申请的内存
	delete[] pBuf;

	pwBuf = NULL;
	pBuf = NULL;

	return retStr;
}

std::string test01::CodeUtils::Utf8ToGbk(const std::string& str)
{
	std::string result;
	WCHAR* strSrc; // 宽字节字符/双字节类型
	LPSTR szRes;
	// LPSTR被定义成是一个指向以NULL(‘\0’)结尾的32位ANSI字符数组指针，
	// LPWSTR是一个指向以NULL结尾的64位双字节字符数组指针

	//获得临时变量的大小
	int i = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, NULL, 0);
	strSrc = new WCHAR[i + 1];
	MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, strSrc, i);
	// MultiByteToWideChar 是 Windows API 中的一个函数，用于在多字节字符集（如 UTF-8）和宽字符集（如 Unicode）之间进行转换
	// CP_UTF8 是一个常量，表示使用 UTF-8 编码。当前系统的 ANSI 代码页（code page）
	// str.c_str() 是一个字符串对象 str 的成员函数，返回一个指向以 null 结尾的字符数组的指针，用于表示要转换的 UTF-8 字符串。
	// - 1 表示要转换的字符串以 null 结尾，函数会根据 null 终止符自动计算字符串的长度。
	// NULL 表示不需要获取转换后的宽字符数据，仅计算所需的缓冲区大小。
	// 0 表示计算所需的缓冲区大小。

	//获得临时变量的大小
	i = WideCharToMultiByte(CP_ACP, 0, strSrc, -1, NULL, 0, NULL, NULL);
	szRes = new CHAR[i + 1];
	WideCharToMultiByte(CP_ACP, 0, strSrc, -1, szRes, i, NULL, NULL);
	// WideCharToMultiByte 是 Windows API 中的一个函数，用于在宽字符集（如 Unicode）和多字节字符集之间进行转换

	result = szRes;
	delete[]strSrc;
	delete[]szRes;

	return result;
}

// 
std::string test01::CodeUtils::WStringToString(const std::wstring& ws)
{
	std::string strLocale = setlocale(LC_ALL, ""); // setlocale-当前程序使用本地化信息

	size_t ptNumOfCharConverted;
	int charArrayCount = ws.size() * 2 + 2;
	char* dst = new char[charArrayCount];
	const wchar_t* wchSrc = ws.c_str();
	wcstombs_s(&ptNumOfCharConverted, dst, charArrayCount, ws.c_str(), charArrayCount); // 安全地将宽字符字符串转换为多字节字符字符串
	std::string strResult = dst;
	delete[] dst;

	setlocale(LC_ALL, strLocale.c_str());
	return strResult;
}

std::wstring test01::CodeUtils::StringToWString(const std::string& str)
{
	std::wstring wContext = L"";
	int len = MultiByteToWideChar(CP_ACP, 0, str.c_str(), str.size(), NULL, 0);
	WCHAR* buffer = new WCHAR[len + 1];
	MultiByteToWideChar(CP_ACP, 0, str.c_str(), str.size(), buffer, len);
	buffer[len] = '\0';
	wContext.append(buffer);
	delete[] buffer;

	return wContext;
}

bool test01::CodeUtils::IsChineseChar(const std::wstring& wstr)
{
	if (wstr.size() == 1)
	{
		unsigned char* pCh = (unsigned char*)&wstr[0];
		if (((*pCh >= 0) && (*pCh <= 0xff)) && (*(pCh + 1) >= 0x4e && *(pCh + 1) <= 0x9f))
		{
			return true;
		}
	}
	return false;
}

std::vector<std::string> test01::CodeUtils::SpiteStringCharacter(const std::string& str)
{
	std::vector<std::string> res;

	std::wstring wContext = StringToWString(str);
	for (int i = 0; i < wContext.length(); ++i)
	{
		std::wstring tmp = wContext.substr(i, 1);
		res.push_back(WStringToString(tmp));
	}

	return res;
}

int test01::CodeUtils::GetStringChineseCharCount(const std::string& str)
{
	std::wstring wContext = StringToWString(str);

	int chineseCharCount = 0;
	for (int i = 0; i < wContext.length(); ++i)
	{
		if (IsChineseChar(wContext.substr(i, 1)))
		{
			++chineseCharCount;
		}
	}

	return chineseCharCount;
}